package com.erp.erp_ui.Cost.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.erp.enums.ModuleTypeEnum;
import com.erp.erp_entitys.Cost.entity.CostApportionmentEntity;
import com.erp.erp_entitys.Cost.entity.CostDetailEntity;
import com.erp.erp_entitys.Cost.entity.CostEntity;
import com.erp.erp_entitys.Cost.entity.CostPaymentEntity;
import com.erp.erp_entitys.Cost.req.*;
import com.erp.erp_entitys.Cost.vo.*;
import com.erp.erp_entitys.money.rsp.CollectionStatistics1Rsp;
import com.erp.erp_entitys.warehouse.entity.AnnexEntity;
import com.erp.erp_entitys.warehouse.entity.PlanInstoreProductEntity;
import com.erp.erp_entitys.warehouse.entity.TempAnnexEntity;
import com.erp.erp_servers.Cost.CostApportionmentService;
import com.erp.erp_servers.Cost.CostDetailService;
import com.erp.erp_servers.Cost.CostPaymentService;
import com.erp.erp_servers.Cost.CostService;
import com.erp.erp_servers.warehouse.IAnnexService;
import com.erp.erp_servers.warehouse.IPlanInstoreProductService;
import com.erp.erp_servers.warehouse.IStockService;
import com.erp.erp_servers.warehouse.ITempAnnexService;
import com.erp.erp_ui.Cost.VO.MergeCostDetailVO;
import com.erp.erp_ui.Cost.VO.MergeDeptAccVO;
import com.erp.erp_ui.Cost.VO.MergeSelectPrimaryVO;
import com.erp.utils.DateUtils;
import com.erp.utils.R;
import com.erp.utils.ResultStatusEnum;
import com.erp.utils.StringUtil;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zjk
 * @version 1.0
 * @description 费用总接口
 * @date 2020/11/28/028 19:12
 */
@Service
public class CostAllService {
    private final CostService costService;

    private final CostDetailService costDetailService;

    private final CostPaymentService costPaymentService;
    /**
     * 附件接口
     */
    private final IAnnexService annexService;
    /**
     * 临时附件接口
     */
    private final ITempAnnexService tempAnnexService;

    private final CostApportionmentService costApportionmentService;

    private final IPlanInstoreProductService planInstoreProductService;

    /**
     * 库存接口
     */
    private final IStockService stockService;
    @Autowired
    public CostAllService(CostService costService,
                          CostDetailService costDetailService,
                          CostPaymentService costPaymentService,
                          IAnnexService annexService,
                          ITempAnnexService tempAnnexService,
                          CostApportionmentService costApportionmentService,
                          IPlanInstoreProductService planInstoreProductService,
                          IStockService stockService) {
        this.costService = costService;
        this.costDetailService = costDetailService;
        this.costPaymentService = costPaymentService;
        this.annexService = annexService;
        this.tempAnnexService = tempAnnexService;
        this.costApportionmentService = costApportionmentService;
        this.planInstoreProductService = planInstoreProductService;
        this.stockService = stockService;
    }

    /**
     * 彻底删除费用
     * @param costId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public R delCostByCostId(Integer costId){
        try {
            CostEntity costEntity=costService.findCostById(costId);
            //删除费用主信息
            costService.delCostByCostId(costId);
            //删除费用明细
            costDetailService.deleteByCostCode(costEntity.getCode());
            return R.build(ResultStatusEnum.SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 根据费用ID集合，修改费用的状态
     * @param costIds
     * @param status
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public R updateCostTypeByCostId(Integer[] costIds, Integer status){
        int num=costService.updateCostTypeByCostId(costIds,status);
        if (num>0){
            //执行入库费用分摊,审批通过累加，审批退回费用分摊数据清零
            if (status==3 || status==1){//3:审批通过,1:审批退回
                updateCostShareAdd(costIds,status);
            }
            return R.build(ResultStatusEnum.SUCCESS);
        }
        return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
    }

    /**
     * 执行入库费用分摊
     * @param costIds
     * @param status
     */
//    @Transactional(rollbackFor = Exception.class)
    private void updateCostShareAdd(Integer[] costIds, Integer status){
        for (int i = 0; i < costIds.length; i++) {

            CostEntity costEntity=costService.findCostById(costIds[i]);
            if (costEntity!=null){
                //根据费用编号获取费用明细
                List<CostDetailEntity> costDetailList=costDetailService.findAllByCode(costEntity.getCode());
                for (CostDetailEntity p:costDetailList){
                    List<CostDetailAndPlanInStoreProductInfo> cdAndPidList =new ArrayList<>();
                    if (status==3){
                        //获取费用明细和备货入库产品信息--查询没有分摊过的信息
                        cdAndPidList = costDetailService.getCostDetailAndPlanInStoreProductInfo(p.getId(),p.getInvoiceCode(),0);
                    }else if (status==1){
                        //获取费用明细和备货入库产品信息--查询已经分摊过的信息
                        cdAndPidList = costDetailService.getCostDetailAndPlanInStoreProductInfo(p.getId(),p.getInvoiceCode(),1);
                    }
                    //体积
                    BigDecimal allVolume=new BigDecimal(0);
                    //数量
                    BigDecimal allNum=new BigDecimal(0);
                    //净重
                    BigDecimal allNetWeight=new BigDecimal(0);
                    //毛重
                    BigDecimal allGrossWeight=new BigDecimal(0);
                    for (CostDetailAndPlanInStoreProductInfo g:cdAndPidList){
                        allVolume=allVolume.add(g.getVolume()).setScale(4,BigDecimal.ROUND_UP);
                        allNum=allNum.add(g.getNum()).setScale(4,BigDecimal.ROUND_UP);
                        allNetWeight=allNetWeight.add(g.getNetWeight()).setScale(4,BigDecimal.ROUND_UP);
                        allGrossWeight=allGrossWeight.add(g.getGrossWeight()).setScale(4,BigDecimal.ROUND_UP);
                    }

                    for (CostDetailAndPlanInStoreProductInfo req:cdAndPidList){
                        CostApportionmentEntity cEntity=new CostApportionmentEntity();
                        cEntity.setCostCode(req.getCostCode());
                        cEntity.setCostDetailId(req.getCostDetailId());
                        cEntity.setPlanInStoreProductId(req.getPlanInStoreProductId());
                        cEntity.setBillno(req.getBillNo());
                        cEntity.setCarryDetailNo(req.getCarryDetailNo());
                        cEntity.setInstoreTime(req.getTime());
                        cEntity.setWarehouseId(req.getWarehouseId());
                        cEntity.setWarehouseName(req.getWarehouseName());
                        cEntity.setApportionmentAmount(req.getShareCostPrice());
                        cEntity.setLotNo(req.getLotNo());
                        cEntity.setProductCode(req.getProductCode());
                        if (req.getNum()!=null){
                            cEntity.setNum(req.getNum().intValue());
                        }

                        cEntity.setGrossWeight(req.getGrossWeight());
                        cEntity.setNetWeight(req.getNetWeight());
                        cEntity.setBulk(req.getVolume());
                        cEntity.setPersonCode(req.getPersonNo());
                        cEntity.setPersonName(req.getPerson());
                        cEntity.setOperatorCode(req.getOperationCode());
                        cEntity.setOperatorName(req.getOperation());
                        //分摊类型 怎么确定？暂时默认体积为2
//                        cEntity.setAllocationtype(Integer.parseInt(req.getAllocationType()));
                        cEntity.setAllocationtype(2);


                        if (status==3){
                            //保存入库费用分摊信息
                            costApportionmentService.insertCostApportionmentInfo(cEntity);
                            p.setShare(1);
                        }else if  (status==1){
                            //删除入库费用分摊信息
                            costApportionmentService.deleteByPrimary(cEntity);
                            p.setShare(0);
                        }
                        // 更改费用明细的分摊字段
                        costDetailService.updateByCostDetailEntity(p);


                        //根据备货入库产品ID查询备货入库信息
                        PlanInstoreProductEntity pProductEntity=planInstoreProductService.queryById(req.getPlanInStoreProductId());

                        //获取旧的分摊金额
                        BigDecimal shareCostPrice=new BigDecimal(0);
                        if (pProductEntity.getShareCostPrice()!=null){
                            shareCostPrice=pProductEntity.getShareCostPrice();
                        }
                        //获取原来的海运费
                        BigDecimal shippingFeeBefore=new BigDecimal(0);
                        if (pProductEntity.getShippingFee()!=null){
                            shippingFeeBefore=pProductEntity.getShippingFee();
                        }
                        //获取原来的关税
                        BigDecimal tariffBefore=new BigDecimal(0);
                        if (pProductEntity.getTariff()!=null){
                            tariffBefore=pProductEntity.getTariff();
                        }
                        //获取原来的美国仓储操作费
                        BigDecimal storageOperationFeeBefore=new BigDecimal(0);
                        if (pProductEntity.getStorageOperationFee()!=null){
                            storageOperationFeeBefore=pProductEntity.getStorageOperationFee();
                        }
                        //获取原来的运输代理服务费
                        BigDecimal transferAgencyFeeBefore=new BigDecimal(0);
                        if(pProductEntity.getTransferAgencyFee()!=null){
                            transferAgencyFeeBefore= pProductEntity.getTransferAgencyFee();
                        }

                        //费用明细的申请金额
                        BigDecimal applicationAmount=req.getApplicationAmount().setScale(4,BigDecimal.ROUND_UP);

                        //计算方式
                        BigDecimal sharePrice =new BigDecimal(0);
                        //怎么确定？
                        //分摊类型
//                        String allocationType=req.getAllocationType();
                        String allocationType="2";
                        switch (allocationType){
                            case "1"://数量
                                sharePrice=(applicationAmount.multiply(req.getNum().divide(allNum,2))).divide(req.getNum(),2).setScale(4,BigDecimal.ROUND_UP);
                                break;
                            case "2"://体积
                                sharePrice= (applicationAmount.multiply(req.getVolume().divide(allVolume,2))).divide(req.getNum(),2).setScale(4,BigDecimal.ROUND_UP);
                                break;
                            case "3"://净重
                                sharePrice=(applicationAmount.multiply(req.getNetWeight().divide(allNetWeight,2))).divide(req.getNum(),2).setScale(4,BigDecimal.ROUND_UP);
                                break;
                            case "4"://毛重
                                sharePrice=(applicationAmount.multiply(req.getGrossWeight().divide(allGrossWeight,2))).divide(req.getNum(),2).setScale(4,BigDecimal.ROUND_UP);
                                break;
                            default:
                        }

                        //费用类型
                        //..(4,9,10,8) /*海运费,美国仓储操作费,运输代理服务费,关税*/
                        switch (req.getFeeCode()){
                            case "4"://海运费
                                if (status==3){
                                    pProductEntity.setShippingFee(shippingFeeBefore.add(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }else if (status==1){
                                    pProductEntity.setShippingFee(shippingFeeBefore.subtract(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }
                                break;
                            case "8"://关税
                                if (status==3){
                                    pProductEntity.setTariff(tariffBefore.add(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }else if (status==1){
                                    pProductEntity.setTariff(tariffBefore.subtract(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }
                                break;
                            case "9"://美国仓储操作费
                                if (status==3){
                                    pProductEntity.setStorageOperationFee(storageOperationFeeBefore.add(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }else if (status==1){
                                    pProductEntity.setStorageOperationFee(storageOperationFeeBefore.subtract(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }
                                break;
                            case "10"://运输代理服务费
                                if (status==3){
                                    pProductEntity.setTransferAgencyFee(transferAgencyFeeBefore.add(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }else if (status==1){
                                    pProductEntity.setTransferAgencyFee(transferAgencyFeeBefore.subtract(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                                }
                                break;
                        }

                        //获取累加之后的海运费
                        BigDecimal shippingFeeAfter=new BigDecimal(0);
                        if (pProductEntity.getShippingFee()!=null){
                            shippingFeeAfter=pProductEntity.getShippingFee().setScale(4,BigDecimal.ROUND_UP);
                        }
                        //获取累加之后的关税
                        BigDecimal tariffAfter=new BigDecimal(0);
                        if (pProductEntity.getTariff()!=null){
                            tariffAfter=pProductEntity.getTariff().setScale(4,BigDecimal.ROUND_UP);
                        }

                        //获取累加之后的美国仓储操作费
                        BigDecimal storageOperationFeeAfter=new BigDecimal(0);
                        if (pProductEntity.getStorageOperationFee()!=null){
                            storageOperationFeeAfter=pProductEntity.getStorageOperationFee().setScale(4,BigDecimal.ROUND_UP);
                        }
                        //获取累加之后的运输代理服务费
                        BigDecimal transferAgencyFeeAfter=new BigDecimal(0);
                        if(pProductEntity.getTransferAgencyFee()!=null){
                            transferAgencyFeeAfter= pProductEntity.getTransferAgencyFee().setScale(4,BigDecimal.ROUND_UP);
                        }

                        if (status==3){//加上新的分摊金额总计
                            pProductEntity.setShareCostPrice(shareCostPrice.add(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                        }else if (status==1){//减掉退回的金额
                            pProductEntity.setShareCostPrice(shareCostPrice.subtract(sharePrice).setScale(4,BigDecimal.ROUND_UP));
                        }

                        //更新备货入库表
                        planInstoreProductService.update(pProductEntity);

                        //更新库存、调拨、销售出库明细的各种费用信息
                        stockService.updateStockAndTransferAndSaleFee(pProductEntity);
                    }
                }
            }
        }
    }



    /**
     * 整合根据出运编码获取备货入库信息
     * @param req
     * @return
     */
    private List<QueryCostDetailWarehouseVO>  getCostDetailWarehouseList(QueryCostDetailWarehouseReq req){
        List<QueryCostDetailWarehouseVO> list=costDetailService.getUnShareCostDetails(req);
        for (QueryCostDetailWarehouseVO p:list) {
            List<QueryPlanInStoreProductInfoVo> productInfoVos=costDetailService.getPlanInStoreInfo(p.getInvoiceCode());
            p.setProductInfoVoList(productInfoVos);
        }
        Iterator iterator=list.iterator();
        while (iterator.hasNext()){
            QueryCostDetailWarehouseVO p= (QueryCostDetailWarehouseVO)iterator.next();
            //如果备货表里没有对应得信息，则去掉该集合
            if (p.getProductInfoVoList().size()==0){
                iterator.remove();
            }
        }

        return list;
    }






    /**
     * 根据费用编号查询费用明细，费用付款明细。。。。
     * @param costCode
     * @return
     */
    public MergeCostDetailVO getCostAll(String costCode){
        //获取费用对象
        CostEntity costEntity=costService.selectByPrimaryKey(costCode);

        MergeCostDetailVO mergeCostDetailVO=new MergeCostDetailVO();

        BeanUtils.copyProperties(costEntity,mergeCostDetailVO);
        mergeCostDetailVO.setCreateTime(DateUtils.format(costEntity.getCreateTime(), DateUtils.DATE_PATTERN));

        //获取费用明细列表
        List<CostDetailEntity> costDetailEntityList=costDetailService.findAllByCode(costEntity.getCode());
        List<CostDetailVO> costDetailVOs=new ArrayList<>();
        for (CostDetailEntity costDetailsInto: costDetailEntityList) {
            CostDetailVO costDetailVO=new CostDetailVO();

            BeanUtils.copyProperties(costDetailsInto,costDetailVO);
            costDetailVO.setSalesmanCode(costDetailsInto.getResponsibilityCode());
            costDetailVO.setSalesmanName(costDetailsInto.getResponsibilityName());
            //外销合同号
            costDetailVO.setContractNo(costDetailsInto.getExportContractCode());
            //采购合同号
            costDetailVO.setStockNoStr(costDetailsInto.getStockCode());
            //单据日期
            costDetailVO.setBillDate(DateUtils.format(costDetailsInto.getBillDate(),DateUtils.DATE_PATTERN));
            costDetailVOs.add(costDetailVO);
        }
        mergeCostDetailVO.setCostDetailVOList(costDetailVOs);

        //获取费用付款明细列表
        List<CostPaymentEntity> costPaymentEntityList=costPaymentService.findAllByCostCode(costEntity.getCode());
        List<CostPaymentVO> costPaymentVOList=new ArrayList<>();
        for (CostPaymentEntity paymentEntity:costPaymentEntityList) {
            CostPaymentVO costPaymentVO=new CostPaymentVO();
            BeanUtils.copyProperties(paymentEntity,costPaymentVO);
            costPaymentVO.setCreateTime(DateUtils.format(paymentEntity.getCreateTime(), DateUtils.DATE_PATTERN));
            costPaymentVOList.add(costPaymentVO);
        }
        mergeCostDetailVO.setCostPaymentList(costPaymentVOList);


        //获取附件详情
        AnnexEntity annexEntity = new AnnexEntity();
        annexEntity.setModuleId(ModuleTypeEnum.MONEY_RECEIVE_COST.getId());
        annexEntity.setParentId(costEntity.getId());
        List<AnnexEntity> annexList = annexService.queryAll(annexEntity);

        List<CostAnnexVO> annexVos=new ArrayList<>();
        if (annexList.size()>0) {
            for (AnnexEntity annex : annexList) {
                CostAnnexVO annexVo = new CostAnnexVO();
                //赋值
                BeanUtils.copyProperties(annex, annexVo);
                //上传时间转换
                annexVo.setUploadTime(DateUtils.format(annex.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置附件为旧附件,用以区分修改时附件状态
                annexVo.setNews(0);
                annexVos.add(annexVo);
            }
        }
        mergeCostDetailVO.setCostAnnexVOList(annexVos);

        //入库费用分摊集合
        List<CostApportionmentEntity> costApportionmentEntityList=costApportionmentService.getCostApportionmentListByPage(costCode);
        List<QueryCostApportionmenVO> voList=new ArrayList<>();
        for (CostApportionmentEntity p:costApportionmentEntityList){
            QueryCostApportionmenVO vo=new QueryCostApportionmenVO();
            BeanUtils.copyProperties(p,vo);
            vo.setInstoreTimeStr(DateUtils.format(p.getInstoreTime(),DateUtils.DATE_PATTERN));
            voList.add(vo);
        }
        mergeCostDetailVO.setCostApportionmenVOList(voList);

        return mergeCostDetailVO;
    }


    /**
     * 封装费用新增，修改页面加载下拉框所需要的数据
     * @return
     */
    public MergeSelectPrimaryVO getSelectPrimary(){
        MergeSelectPrimaryVO selectPrimaryVO=new MergeSelectPrimaryVO();
        //获取编号
        String code=costService.selectCodeByCode();
        String newCode=findCodeEntity(code);

        selectPrimaryVO.setCode(newCode);


        //获取币种集合
        //selectPrimaryReq.getCurrCode()
        //selectPrimaryVO.setCurr(List<curr>);

        //获取收款单位
        List<QueryPayeeVO>  payeeVOS=AllPayee();
        selectPrimaryVO.setPayeeVOS(payeeVOS);

        //获取制单单位
        List<QueryBillCompanyVO>  billCompanyVOList=costService.selectCompanyForBillCompanyCode();
        selectPrimaryVO.setBillCompanyVOS(billCompanyVOList);

        //获取所有用户
        List<QueryAllUserVO>  userVOS=costService.selectAllUser();
        selectPrimaryVO.setAllUserVOS(userVOS);
        return selectPrimaryVO;
    }

    /**
     * 获取收款单位信息
     * @return
     */
    public List<QueryPayeeVO> AllPayee(){
        return costService.selectCustomer2ForPayee();
    }

    /**
     * 封装核算部门和员工
     * @param deptAccReq
     * @return
     */
    public MergeDeptAccVO getDeptAcc(QueryDeptAccReq deptAccReq){
        MergeDeptAccVO deptAccVO=new MergeDeptAccVO();
        List<QueryDeptVO> deptVOS=costService.selectDeptByAcc(deptAccReq);
        deptAccVO.setDeptVOS(deptVOS);
        List<QueryAccVO> accVOS=costService.selectAccByDept(deptAccReq);
        deptAccVO.setAccVOS(accVOS);
        return deptAccVO;
    }


    /**
     * 返回可用编码,,
     * @param code
     * @return
     */
    private String findCodeEntity(String code){
        String newCode=code;
        CostEntity costEntity=costService.selectByPrimaryKey(code);
        if (costEntity!=null){
            String codeSub=code.substring(code.indexOf("20"));
            long codeLong=Long.valueOf(codeSub);
            long newCodeLong=codeLong+1;

            String codeSub2=code.substring(0,code.indexOf("20"));
            newCode=codeSub2+newCodeLong;
        }
        CostEntity newCostEntity=costService.selectByPrimaryKey(newCode);
        if (newCostEntity!=null){
            newCode=findCodeEntity(newCode);
        }
        return newCode;
    }
    /**
     * 添加，修改费用信息
     * @param costReq
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public R ModifyAndInsertCost2(ModifyAndInsertCostReq2 costReq){
        Integer costId=costReq.getId();
        if (StringUtils.isEmpty(costReq.getIsViewFile())){
            CostEntity oldCostEntity=costService.selectByPrimaryKey(costReq.getCode());
            String newCode=costReq.getCode();
            //操作1：新增，2：修改
            if (costReq.getSetType()==1&&oldCostEntity!=null){
                newCode=findCodeEntity(costReq.getCode());
            }



                //修改，添加费用主信息
                CostEntity costEntity=new CostEntity();
                BeanUtils.copyProperties(costReq, costEntity);
                costEntity.setPayeeCode(costReq.getPayeeCode());
                costEntity.setPayeeName(costReq.getInputPayeeName());
                costEntity.setBankName(costReq.getInputBankName());
                costEntity.setBankAccount(costReq.getInputBankAccount());

                //1：保存，2：提交
                //保存,保存到草稿箱
                if(costReq.getInsertStatus()==1){
                    costEntity.setStatus(1);
                }
                //提交,提交到待批箱
                if(costReq.getInsertStatus()==2){
                    costEntity.setStatus(2);
                }

                //添加费用主信息
                //操作1：新增，2：修改
                if (costReq.getSetType()==1){
                    //设置编号
                    costEntity.setCode(newCode);
                    //1：直接费用，2：间接费用
                    if (costReq.getCostType().equals("直接费用")){
                        costEntity.setCostType(1);
                    }else if(costReq.getCostType().equals("间接费用")){
                       costEntity.setCostType(2);
                    }
                    int num=costService.insertSelective(costEntity);
                    if (num==1){
                        CostEntity tempCost=costService.selectByPrimaryKey(newCode);
                        costId=tempCost.getId();
                    }
                }
                //修改费用主信息
                if (costReq.getSetType()==2){
                    costEntity.setValid(1);
                    costService.updateByCostEntity(costEntity);
                    CostEntity tempCost=costService.selectByPrimaryKey(newCode);
                    costId=tempCost.getId();
                }




                //获取传递过来的费用明细
                List<costDetailsInto> costDetailsIntoList=costReq.getCostDetails();
                //定义空的费用明细集合
                List<CostDetailEntity> newCostDetailEntityList=new ArrayList<>(costDetailsIntoList.size()+5);
                //复制集合
                for (costDetailsInto costDetailsInto: costDetailsIntoList) {
                    CostDetailEntity costDetailEntity=new CostDetailEntity();
                    BeanUtils.copyProperties(costDetailsInto,costDetailEntity);
                    costDetailEntity.setResponsibilityCode(costDetailsInto.getSalesmanCode());
                    costDetailEntity.setResponsibilityName(costDetailsInto.getSalesmanName());
                    costDetailEntity.setStockCode(costDetailsInto.getStockNoStr());
                    costDetailEntity.setExportContractCode(costDetailsInto.getContractNo());
                    newCostDetailEntityList.add(costDetailEntity);
                }


                //新增费用明细
                if (costReq.getSetType()==1&&newCostDetailEntityList.size()>0){
                    //添加费用明细信息
                    for (CostDetailEntity newCostDetail:  newCostDetailEntityList) {
                        //设置费用主编号
                        newCostDetail.setCostCode(newCode);
                        //添加费用明细实体
                        costDetailService.insertSelective(newCostDetail);
                    }
                }
                //修改费用明细
                if (costReq.getSetType()==2){
                    //根据费用主编号查询费用明细集合
                    List<CostDetailEntity> oldCostDetailList=costDetailService.findAllByCode(newCode);
                    //获取旧明细ID集合
                    List<Integer> oldIds=oldCostDetailList.stream().map(p -> p.getId()).collect(Collectors.toList());
                    //获取新明细ID集合
                    List<Integer> newIds=newCostDetailEntityList.stream().map(p -> p.getId()).collect(Collectors.toList());

                    if (newIds.size()!=0){
                        //获得删除的元素
                        oldIds.removeAll(newIds);
                    }

                    //修改删除元素的状态为无效
    //                if (oldIds.size()!=0){
    //                    costDetailService.updateCostDetaiInvalid(0, oldIds);
    //                }
                    //直接删除明细
                    if (oldIds.size()!=0){
                        costDetailService.delCostDetaiInvalid(oldIds);
                    }

                    //添加费用明细信息
                    for (CostDetailEntity newCostDetail:  newCostDetailEntityList) {
                        //设置费用主编号
                        newCostDetail.setCostCode(newCode);
                        //判断ID为空则添加，负责修改
                        if (newCostDetail.getId() == null){
                            costDetailService.insertSelective(newCostDetail);
                        }else{
                            costDetailService.updateByCostDetailEntity(newCostDetail);
                        }
                    }
                }
            }
            List<CostAnnexReq> newAnnexReqs=costReq.getAnnexReqs();
            //添加附件信息
            boolean flag = addAnnex(newAnnexReqs, costId, costReq.getOperatorName(), costReq.getOperatorCode(),costReq.getSetType());
            //删除临时附件信息
            deleteTempAnnex(newAnnexReqs);
            if(!flag){
                return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
            }

            return R.build(ResultStatusEnum.SUCCESS);

    }
    /**
     * 批量处理临时附件信息，将临时附件设置为失效
     * @param annexReqs
     */
    private void deleteTempAnnex(List<CostAnnexReq> annexReqs){
        //没有附件
        if(CollectionUtils.isEmpty(annexReqs)){
            return;
        }
        //存在附件
        for(CostAnnexReq annex : annexReqs){
            if(null != annex.getNews()){
                //旧附件,不用修改
                continue;
            }
            TempAnnexEntity tempAnnex = new TempAnnexEntity();
            //设置临时附件id
            tempAnnex.setId(annex.getId());
            //设置修改时间
            tempAnnex.setUpdateTime(new Date());
            //将附件设置为失效
            tempAnnex.setValid(0);
            tempAnnexService.update(tempAnnex);
        }

    }
    /**
     * 附件新增
     * @param annexReqs 附件信息集合
     * @param costId 费用id
     * @param operator 操作人
     * @param operatorNo 操作人编码
     * @return 是否新增成功(true:成功 false:失败 )
     */
    private boolean addAnnex(List<CostAnnexReq> annexReqs, Integer costId, String operator, String operatorNo,Integer setType) {
        //新增附件明细
        if (setType==1){
            //添加费用明细信息
            return foreachAnnexReq(annexReqs, costId,operator,operatorNo);
        }
        //修改附件明细
        if (setType==2){
            //获取新附件id集合
            List<Integer> newIds = annexReqs.stream().map(p -> p.getId()).collect(Collectors.toList());
            //获取旧的附件id集合开始
            //通过费用id获取旧附件附件信息
            AnnexEntity annex = new AnnexEntity();
            annex.setModuleId(ModuleTypeEnum.MONEY_RECEIVE_COST.getId());
            annex.setParentId(costId);
            //获取旧附件信息,并得到旧附件ID的集合
            List<Integer> oldIds = annexService.queryAll(annex).stream().map(p -> p.getId()).collect(Collectors.toList());

            //获得删除的附件
            if (newIds.size()>0){
                oldIds.removeAll(newIds);
            }
            //修改附件的状态为无效
            if (oldIds.size()>0){
                costService.updateAnnexValid(oldIds,0);
            }

            //添加费用明细信息
            return foreachAnnexReq(annexReqs, costId,operator,operatorNo);
        }
        return false;
    }

    /**
     * 循环添加附件的方法
     * @param annexReqs
     * @param costId
     * @param operator
     * @param operatorNo
     * @return false添加失败，true：添加成功
     */
    public boolean foreachAnnexReq(List<CostAnnexReq> annexReqs, Integer costId, String operator, String operatorNo){
        try {
            boolean flag=true;
            //添加费用明细信息
            for (CostAnnexReq annexReq:  annexReqs) {
                //旧附件的news属性为0，新附件的news属性为null
                if (annexReq.getNews()==null){
                    AnnexEntity annex = new AnnexEntity();
                    BeanUtils.copyProperties(annexReq, annex);
                    //设置关联模块id
                    annex.setModuleId(ModuleTypeEnum.MONEY_RECEIVE_COST.getId());
                    //设置关联模块父id
                    annex.setParentId(costId);
                    //设置上传时间
                    annex.setUploadTime(DateUtils.convertStringToDate(annexReq.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                    //设置修改时间
                    annex.setUpdateTime(new Date());
                    //设置操作人
                    annex.setOperator(operator);
                    //设置操作人编码
                    annex.setOperatorNo(operatorNo);
                    //设置数据有效
                    annex.setValid(1);

                    Integer num= annexService.insert(annex);
                    if (num>0){
                        flag= true;
                    }else{
                        flag=false;
                    }
                }
            }
            return flag;
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }
    }


    @Transactional
    public R ModifyAndInsertCost(ModifyAndInsertCostReq2 costReq){
        boolean costFlag=addCost(costReq);
        boolean costDetailFlag=addCostDetail(costReq);
        if(costFlag&&costDetailFlag){
            return R.build(ResultStatusEnum.SUCCESS);
        }
        return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
    }

    /**
     * 修改，添加费用
     * @param costReq
     * @return
     */
    public Boolean addCost(ModifyAndInsertCostReq2 costReq){
        try {
        CostEntity oldCostEntity=costService.selectByPrimaryKey(costReq.getCode());
        //添加
        CostEntity costEntity=new CostEntity();

            //币种
            costEntity.setCurrencyCode(costReq.getCurrencyCode());
            costEntity.setCurrencyName(costReq.getCurrencyName());
            //人民币汇率
            costEntity.setRmbRate(costReq.getRmbRate());
            //美金汇率
            costEntity.setUsdRate(costReq.getUsdRate());
            //收款单位
            List<QueryPayeeVO>  payeeVOS= costService.selectCustomer2ForPayee(costReq.getPayeeCode());
            for (QueryPayeeVO pa:payeeVOS){
                costEntity.setPayeeCode(pa.getPayeeCode());
                costEntity.setPayeeName(pa.getPayeeName());
            }

            costEntity.setBankName(costReq.getInputBankName());
            costEntity.setBankAccount(costReq.getInputBankAccount());
            //costEntity.setCostPaymentId();
            costEntity.setTotalAmount(costReq.getTotalAmount());
            //点击付款的时候才会有
            //costEntity.setTotalCost();
            //costEntity.setTotalCostCreateTime();
            //费用拆分的时候才会有
            //costEntity.setAmountSplit();
            //costEntity.setUndividedAmount();
            costEntity.setCreateTime(costReq.getCreateTime());
            //制单公司编号billCompanyName
            costEntity.setBillCompanyCode(costReq.getBillCompanyCode());
            costEntity.setBillCompanyName(costReq.getBillCompanyName());
            //操作人员编号
            costEntity.setOperatorCode(costReq.getOperatorCode());
            costEntity.setOperatorName(costReq.getOperatorName());
            //业务员，费用表里用不上
            //costEntity.setSalesmanName();
            //单据信息，费用表用不上
            //costEntity.setBillInformation();

            costEntity.setDescription(costReq.getDescription());
            /**
             *单据状态/类型（1：草稿箱，2：待批箱，3：已批箱，4：完成箱，5垃圾箱）
             * 1：保存，2：提交
             * 保存：费用状态为 1
             * 提交：费用状态为 2
             */
            costEntity.setStatus(costReq.getInsertStatus());
            /**
             * 是否有效(0:无效 1:有效)
             */
            costEntity.setValid(1);

            //添加费用主信息
            if (costReq.getSetType()==1){
                costEntity.setCode(costReq.getCode());
                //1：直接费用，2：间接费用
                if (costReq.getCostType().equals("直接费用")){
                    costEntity.setCostType(1);
                }else if(costReq.getCostType().equals("间接费用")){
                    costEntity.setCostType(2);
                }
                if (oldCostEntity==null){
                    costService.insertSelective(costEntity);
                }
            }
            //修改费用主信息
            if (costReq.getSetType()==2){
                costService.updateByCostEntity(costEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;

    }

    /**
     * 修改，添加费用明细
     * @param costReq
     * @return
     */
    public Boolean addCostDetail(ModifyAndInsertCostReq2 costReq){

        try {

            List<costDetailsInto> costDetailsIntoList=costReq.getCostDetails();
            for (com.erp.erp_entitys.Cost.req.costDetailsInto costDetailsInto:costDetailsIntoList){
                CostDetailEntity costDetailEntity=new CostDetailEntity();
                //核算人员编号
                costDetailEntity.setAccountantCode(costDetailsInto.getAccountantCode());
                costDetailEntity.setAccountantName(costDetailsInto.getAccountantName());
                costDetailEntity.setApplicationAmount(costDetailsInto.getApplicationAmount());

                costDetailEntity.setCostClassification(costDetailsInto.getCostClassification());


                costDetailEntity.setDepartmentCode(costDetailsInto.getDepartmentCode());
                costDetailEntity.setDepartmentName(costDetailsInto.getDepartmentName());
                costDetailEntity.setExportContractCode(costDetailsInto.getContractNo());
                costDetailEntity.setFeeName(costDetailsInto.getFeeName());
                costDetailEntity.setFeeCode(costDetailsInto.getFeeCode());
                costDetailEntity.setIncreaseCode(costDetailsInto.getIncreaseCode());
                costDetailEntity.setInvoiceCode(costDetailsInto.getInvoiceCode());
                //承担人员编号
                costDetailEntity.setResponsibilityCode(costDetailsInto.getSalesmanCode());
                costDetailEntity.setResponsibilityName(costDetailsInto.getSalesmanName());
                costDetailEntity.setSpecialDesc(costDetailsInto.getSpecialDesc());
                costDetailEntity.setStockCode(costDetailsInto.getStockNoStr());
                costDetailEntity.setCostClassification(costDetailsInto.getCostClassification());
                costDetailEntity.setValid(1);

                if (costReq.getSetType()==1){
                    costDetailEntity.setCostCode(costReq.getCode());
                    //添加费用明细信息
                    costDetailService.insertSelective(costDetailEntity);
                }
                if (costReq.getSetType()==2){
                    //修改费用明细信息
                    //修改之前先删除,再添加
                    costDetailService.deleteByCostCode(costReq.getCode());
                    //添加费用明细信息
                    costDetailService.insertSelective(costDetailEntity);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 获取String类型不为空数据
     *
     * @param value 目标数据
     * @return 不为空数据
     */
    private String getNotNullOfStringInfo(String value) {
        if (StringUtils.isEmpty(value)) {
            return "";
        } else {
            return value;
        }
    }

    /**
     * 获取BigDecimal类型不为空的数据
     *
     * @param value 目标数据
     * @return 不为空数据
     */
    private BigDecimal getNotNullOfBigDecimalInfo(BigDecimal value) {
        if (StringUtil.isNotEmpty(value)) {
            return value;
        } else {
            return new BigDecimal("0");
        }
    }

    /**
     * 费用统计--分页
     * @param req
     * @return
     */
    public PageInfo<QueryCostStatistics1VO> costStatistics1ListByPage(QueryCostStatistics1Req req) {
        List<QueryCostStatistics1VO> costStatistics1VOS=costService.costStatistics1List(req);
        PageInfo pageInfo=new PageInfo(costStatistics1VOS);
        pageInfo.setList(costStatistics1VOS);
        return pageInfo;
    }
    /**
     * 费用统计--导出
     * @param req
     * @return
     */
    public JSONObject costStatistics1Export(QueryCostStatistics1Req req) {
        List<QueryCostStatistics1VO> costStatistics1VOS=costService.costStatistics1List(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleCollectionFirstInfo();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if (CollectionUtils.isEmpty(costStatistics1VOS)) {
            obj.put("data", data);
            return obj;
        }
        excelCollectionFirstInfoExport(data, costStatistics1VOS);
        obj.put("data", data);
        return obj;
    }
    private JSONArray getTitleCollectionFirstInfo() {
        JSONArray obj = new JSONArray();
        obj.add("序号");
        obj.add("登记编号");
        obj.add("收款单位");
        obj.add("币种");
        obj.add("RMB汇率");
        obj.add("USD汇率");
        obj.add("费用操作员");
        obj.add("单据类型");
        obj.add("费用类型");
        obj.add("登记日期");
        obj.add("实付日期");
        obj.add("实付金额");
        obj.add("发票号码");
        obj.add("发票日期");
        obj.add("增票号");
        obj.add("外销合同号");
        obj.add("采购合同号");
        obj.add("费用名称");
        obj.add("申请金额");
        obj.add("承担人员");
        obj.add("核算部门");
        obj.add("核算人员");
        obj.add("特殊备注");
        return obj;
    }
    private void excelCollectionFirstInfoExport(JSONArray data, List<QueryCostStatistics1VO> list) {
        //费用实付金额
        BigDecimal paymentCost = new BigDecimal("0");
        //申请金额
        BigDecimal applicationAmount = new BigDecimal("0");

        int i = 0;
        for (QueryCostStatistics1VO vo : list) {
            JSONArray infoList = new JSONArray();
            infoList.add(++i);
            infoList.add(getNotNullOfStringInfo(vo.getCode()));
            infoList.add(getNotNullOfStringInfo(vo.getPayeeName()));
            infoList.add(getNotNullOfStringInfo(vo.getCurrencyName()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getRmbRate()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUsdRate()));
            infoList.add(getNotNullOfStringInfo(vo.getOperatorName()));
            infoList.add(getNotNullOfStringInfo(vo.getStatus()));
            infoList.add(getNotNullOfStringInfo(vo.getCostType()));
            infoList.add(getNotNullOfStringInfo(vo.getCreateTimeStr()));
            infoList.add(getNotNullOfStringInfo(vo.getTotalCostCreateTimeStr()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getPaymentCost()));
            infoList.add(getNotNullOfStringInfo(vo.getInvoiceCode()));
            infoList.add(getNotNullOfStringInfo(vo.getInvoiceDateStr()));
            infoList.add(getNotNullOfStringInfo(vo.getIncreaseCode()));
            infoList.add(getNotNullOfStringInfo(vo.getExportContractCode()));
            infoList.add(getNotNullOfStringInfo(vo.getStockCode()));
            infoList.add(getNotNullOfStringInfo(vo.getFeeName()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getApplicationAmount()));
            infoList.add(getNotNullOfStringInfo(vo.getDepartmentName()));
            infoList.add(getNotNullOfStringInfo(vo.getAccountantName()));
            infoList.add(getNotNullOfStringInfo(vo.getSpecialDesc()));

            if (StringUtil.isNotEmpty(vo.getPaymentCost())) {
                paymentCost = paymentCost.add(vo.getPaymentCost());
            }
            if (StringUtil.isNotEmpty(vo.getApplicationAmount())) {
                applicationAmount = applicationAmount.add(vo.getApplicationAmount());
            }
            data.add(infoList);
        }
        //合计
        JSONArray titleList = new JSONArray();
        titleList.add("合计");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add(paymentCost);
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add(applicationAmount);
        titleList.add("");
        titleList.add("");
        titleList.add("");

        data.add(titleList);

    }




    /**
     * 费用支付统计--分页
     * @param req
     * @return
     */
    public PageInfo<QueryCostStatistics2VO> costStatistics2List(QueryCostStatistics1Req req) {
        List<QueryCostStatistics2VO> costStatistics2VOS=costService.costStatistics2List(req);
        PageInfo pageInfo=new PageInfo(costStatistics2VOS);
        pageInfo.setList(costStatistics2VOS);
        return pageInfo;
    }

    /**
     * 费用支付统计--导出
     * @param req
     * @return
     */
    public JSONObject costStatistics2Export(QueryCostStatistics1Req req) {
        List<QueryCostStatistics2VO> costStatistics2VOS=costService.costStatistics2List(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleCollectionSecondInfo();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if (CollectionUtils.isEmpty(costStatistics2VOS)) {
            obj.put("data", data);
            return obj;
        }
        excelCollectionSecondInfoExport(data, costStatistics2VOS);
        obj.put("data", data);
        return obj;
    }
    private JSONArray getTitleCollectionSecondInfo() {
        JSONArray obj = new JSONArray();
        obj.add("序号");
        obj.add("登记编号");
        obj.add("收款单位");
        obj.add("币种");
        obj.add("RMB汇率");
        obj.add("USD汇率");
        obj.add("费用操作员");
        obj.add("单据类型");
        obj.add("费用类型");
        obj.add("登记日期");
        obj.add("实付日期");
        obj.add("外销合同号");
        obj.add("采购合同号");
        obj.add("费用名称");
        obj.add("备注");
        obj.add("总金额");
        obj.add("实付金额");
        obj.add("未付金额");
        obj.add("支付情况");
        obj.add("制单公司");
        return obj;
    }
    private void excelCollectionSecondInfoExport(JSONArray data, List<QueryCostStatistics2VO> list) {
        //申请金额
        BigDecimal totalAmount = new BigDecimal("0");
        //费用实付金额
        BigDecimal paymentCost = new BigDecimal("0");
        //未付金额
        BigDecimal unPaymentCost = new BigDecimal("0");

        int i = 0;
        for (QueryCostStatistics2VO vo : list) {
            JSONArray infoList = new JSONArray();
            infoList.add(++i);
            infoList.add(getNotNullOfStringInfo(vo.getCode()));
            infoList.add(getNotNullOfStringInfo(vo.getPayeeName()));
            infoList.add(getNotNullOfStringInfo(vo.getCurrencyName()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getRmbRate()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUsdRate()));
            infoList.add(getNotNullOfStringInfo(vo.getOperatorName()));
            infoList.add(getNotNullOfStringInfo(vo.getStatus()));
            infoList.add(getNotNullOfStringInfo(vo.getCostType()));
            infoList.add(getNotNullOfStringInfo(vo.getCreateTimeStr()));
            infoList.add(getNotNullOfStringInfo(vo.getTotalCostCreateTimeStr()));
            infoList.add(getNotNullOfStringInfo(vo.getExportContractCode()));
            infoList.add(getNotNullOfStringInfo(vo.getStockCode()));
            infoList.add(getNotNullOfStringInfo(vo.getFeeName()));
            infoList.add(getNotNullOfStringInfo(vo.getDescription()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalAmount()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getPaymentCost()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUnPaymentCost()));
            infoList.add(getNotNullOfStringInfo(vo.getCostPaymentType()));
            infoList.add(getNotNullOfStringInfo(vo.getBillCompanyName()));
            if (StringUtil.isNotEmpty(vo.getTotalAmount())) {
                totalAmount = totalAmount.add(vo.getTotalAmount());
            }
            if (StringUtil.isNotEmpty(vo.getPaymentCost())) {
                paymentCost = paymentCost.add(vo.getPaymentCost());
            }
            if (StringUtil.isNotEmpty(vo.getUnPaymentCost())) {
                unPaymentCost = paymentCost.add(vo.getUnPaymentCost());
            }
            data.add(infoList);
        }
        //合计
        JSONArray titleList = new JSONArray();
        titleList.add("合计");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add(totalAmount);
        titleList.add(paymentCost);
        titleList.add(unPaymentCost);
        titleList.add("");
        titleList.add("");

        data.add(titleList);

    }

}
